Allow building an array_string from a const char*#5
Allow building an array_string from a const char*#5matthijskooijman wants to merge 3 commits intoakrzemi1:masterfrom
Conversation
This adds a public converting constructor that accepts a const char*, and modifies the existing private converting constructor to simply accept any parameter type (as long as it supports constexpr indexing, it should work).
|
I am not comfortable providing a constructor from a pointer. Instead, I have added function Would that be satisfactory for your use case? |
Why not? In a constexpr context, AFAICS the compiler will perform static bounds checks so this should be safe? What I don't like about your suggested solution is that:
What I liked about the Ideally, you could do more kinds of processing (also replacing characters in a string, or more generic substring operations, etc.) in the same way, but I now see that the Carrying this thought further, it seems you would get more flexibility if you interpret the One thing you cannot really implement in this way is string operations that increase the string length in a way that is not bounded by type parameters (e.g. when the resulting length depends on string contents and a upper bound cannot be selected statically), but in these cases you can probably explicitly specify an upper bound, and raise a compile-time error when the bound is exceeded, which should probably be sufficient. How does that sound? |
When you pass me a pointer, it is just a pointer. I have no guarantee if it points to a null-terminated char sequence. I cannot apply some validations. Also, I cannot statically figure out the size.
I appreciate why this is a problem. Let me think about a satisfactory solution.
If you are referring to the limitations of this implementation, then yes, it is not a full static string processing: only the sizes of strings. |
|
Maybe what you need is a C++17 #include <experimental/string_view>
#include <iostream>
using std::experimental::string_view;
constexpr string_view s {"/user/me/project/file.cpp"};
constexpr auto i = s.find_last_of("/");
constexpr auto j = i == s.npos ? 0 : i + 1;
constexpr string_view fname = s.substr(j);
int main()
{
std::cout << fname << std::endl;
}Here's a live example: https://wandbox.org/permlink/0kNenlD54cvtZVOf |
|
Furthermore, |
|
I translated my ideas into some code, since that is often easier to talk about. See the last commit I pushed to this PR. I essentially changed the meaning of the I also added a I also added the Some remarks regarding the code:
I guess the last point would be the biggest point to discuss. I think that to conveniently support generic string processing, the |
|
Thank you for the submission. When I have some more spare time, I will analyze this in detail. I understand that the main idea is to track the "capacity" statically, and "length" dynamically. |
|
@akrzemi1, did you perhaps find some time to look at this yet? No pressure, just a gentle reminder :-) |
|
@matthijskooijman: I am sorry but I had to put it in queue due to other commitments and personal life. I did look at it. I think I know how to handle it (provide three specializations of the template: for references to static array, for copied array, and for copied array with fixed capacity but dynamic length). But in honesty, it will take me some time to do this. Sorry for the delay. |
|
I have implemented part of your proposed change: you can take suffixes but not arbitrary substrings. constexpr auto fpath = sstr::literal("path/fname");
constexpr auto fname = sstr::suffix(fpath, 5);
// decltype(fname) is sstr::string_literal_suffix<10>
// fname.size() == 5
constexpr auto full_fname = fname + ".txt";
// decltype(fname) is sstr::array_string_suffix<10 + 4>
// fname.size() == 9
std::cout << full_fname << std::endl;
// outputs: "fname.txt"I think it should handle your use case? |
This adds a public converting constructor that accepts a const char*,
and modifies the existing private converting constructor to simply
accept any parameter type (as long as it supports constexpr indexing, it
should work).
By adding this, you can do more complicated string processing in constexpr functions, and then store the result in a new char array using this new constructor. This allows, for example, to implement a compile-time
basenamefunction (see my blog for an example: https://www.stderr.nl/Blog/Software/Cpp/CompiletimeBasename.html).